/**
 * Node中的热重载 ： supervisor 
 *  使用supervisor代替node命令即可  
 *  全局安装： npm i supervisor -g
 *  supervisor demo1.js 报错：
 *      xxx : 无法加载文件 ..... 因为在此系统上禁止运行脚本。有关详细信息，请参阅 http://go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
 *    解决方案： 
 *      node安装目录下删除 supervisor.ps1 即可 
 *      同理 其他安装的内容运行报上述错误：node安装目录下删除 xxx.ps1 即可 
 * 
 * 
 * 1. 安装： npm i koa
 *      
 *  客户端从发送请求到看到内容过程中
 * 服务器： 接收到请求(request) -> 处理请求，生成数据 -> 发送数据(response)
 * KOA ：  request -> middleware ->  response
 * KOA 处理好了request和response，只需要写中间层即可
 *  也就是说 无需手动设置请求头响应头等信息，无需response.end() 等
 */

// 
const koa = require('koa') //相当于http

const app = new koa()  // 等同于http.createServer()
// 注册中间件，可注册多个，但是要通过调用next()才会继续往下一个中间件执行
app.use((ctx, next) => {

})

/**
 * koa 提供了一些好用的APi
 *  Application：当前应用的对象 ，即 new koa()的实例对象，下有一个Context对象，Context对象又有request和response子对象
 *     - Context
 *       -   request
 *       -  response
 *
 *  Application下有use(),listen()等方法，error事件
 *      use():注册中间件，可以通过修饰async，为异步中间件；
 *              回调函数中第一个参数context对象：每一次请求都会包装一个context对象，
 *              第二个参数next ： 每一个中间件都是一个迭代器
 *
 * app.on(error,(err,ctx)=>{}) 错误处理
 *
 * Context对象：
 *      .req :原生Node中的request对象
 *      .res: 原生Node中的response对象
 *    在Koa中尽量使用koa提供的封装对象，因为绕过koa的对象进行操作处理是不被支持的！！
 *      .request： koa的request对象
 *              .header: 头对象信息 ，可获取/赋值
 *              .method: 请求方法 ， 可获取/赋值
 *              .length： 请求正文长度
 *              .url： 请求ur ， l可获取/赋值
 *              .orignalURL：原始url，不包含协议与主机部分
 *              .href: 完整的url，包含协议，主机，请求串
 *              .path: url路径部分 获取/赋值
 *              .querystring: url中的查询字符串 即?后面的内容
 *              .search: 带?的querystring 获取/赋值
 *              .host
 *              .hostname
 *              .URL : 解析过的url对象
 *              .type: 请求头中的content-type
 *              .charset: 请求头中的charset
 *              .query : 解析后的querystring对象 获取/赋值
 *              .fresh : 判断缓存设置是否有效 true表示有效
 *              .stale : 与fresh相反
 *              .protocol :请求使用的协议
 *              .secure :是否是安全协议 protocol=="https"
 *              .ip :请求客户端ip
 *              .ips: 请求客户端所有IP
 *              .is(types...) : 判断提交内容的MIME类型
 *              .socket : request.socket对象
 *              .get() : 获取请求头的通用方法
 *
 *      .response： koa的response对象
 *              .header:响应头对象 （别名：headers）
 *              .socket :response.socket对象
 *              .status ： 响应状态码     获取/设置
 *              .message : 响应状态码描述文本  获取/设置
 *              .body : 响应内容 获取/设置 （koa会默认设置状态码为200或者204，同时会根据返回的数据类型自动设置content-type）
 *                      string：text/html 或 text/plain
 *                      buffer/Stream : application/octet-stream
 *                      object: application/json
 *              .get() : 获取头信息
 *              .set() : 设置头信息
 *              .append() : 追加头信息
 *              .remove() : 移除头信息
 *              .type : 获取设置content-type
 *              .is(types...) : 判断content-type
 *              .redirect(url) : 重定向，默认重定向状态码为302，可以通过status进行设置
 *              .attachment(filename): 设置下载文件头，filename为下载文件头的名称
 *
 *  以上request对象和response对象中的子对象都可以直接通过context对象使用
 * 也就是说 ctx.response.body == ctx.body
 *
 *      .state：用户数据存储空间  (也就是说通过.state去处理多个中间件之间的数据通信，当然也可以使用context.xxx；但是不推荐，避免对象变量污染)
 *      .app:当前应用程序实例-Application对象
 *      .cookies对象：
 *              get(name,[options])
 *              set(name,value,[options])
 *                 -option:
 *                      .maxAge .expires .domain .httpOnly
 *      .throw(statusCode,message,[options]) : 推荐使用 抛错处理 默认状态码为500
 *
 *
 *
 *  ====================================================================
 *  Koa 中间件
 *      koa-static-cache : 静态文件代理服务
 *      koa-router : 路由
 *      koa-swig : 模板引擎
 *      koa-bodyparser : body解析   https://github.com/koajs/bodyparser
 *      koa-multer : formData解析
 *      koa-session: 设置session（加密cookie）
 *
 *
 *
 * koa-static-cache : https://github.com/koajs/static-cache/
 *     安装 koa-static-cache ： npm i koa-static-cache -S
 *        app.use(staticCache(静态资源文件路径,{
 *              ...options
 *        }))
 *
 *
 * koa-router: https://github.com/ZijianHe/koa-router
 *  非RESTful的url设计：
 *      http://127.0.0.1/user/add  新增用户
 *      http://127.0.0.1/user/query/1 查询用户
 *      http://127.0.0.1/user/delete/1 删除用户
 *   问题：
 *      URL反映的是资源的位置，不应该带有操作，换句话说，对资源的操作不应该改变资源的定位
 *
 * RESTful的url设计： （representational state transfer）表象性状态转变
 *   使用http中的method来表述动作
 *      POST : http://127.0.0.1/user/add  新增用户
 *      GET  : http://127.0.0.1/user/1    查询用户
 *      DELETE : http://127.0.0.1/user/1  删除用户
 *
 * HTTP中的method：
 *   GET : 获取资源
 *   POST: 新建资源
 *   PUT : 更新资源
 *   DELETE: 删除资源
 *
 * koa-router 内置了 get|put|post|patch|delete|del
 *
 *
 * koa-swig 模板引擎    https://www.npmjs.com/package/koa-swig
 *  安装： npm i koa-swig -S
 *  render = require('koa-swig')
 *  co  = require('co')    koa v2需要co模块
 *  把渲染方法挂载到Context下
 *    app.context.render = co.wrap(render({
 *        root:'模板存放目录',
 *        autoescape:'是否自动escape编码',  即是否使用html格式编码 true为text格式 false为html格式(支持标签)    （一般为安全起见设置为text格式即为true）
 *        cache:'是否启用缓存',  false, 'memory':把解析渲染后的结果保存在内存中，即：改变HTML DOM元素后再次访问当前浏览器，不会对原界面DOM发生改变，但是服务器数据的改变是会发生改变的  一般用于线上模式
 *        ext:'模板后缀，html...'
 *    }))
 *   异步中间件渲染文件
 *    app.use(async ctx => ctx.body = await ctx.render('index'));
 *
 * 模板语法：
 *  输出
 *     {{ 表达式 }}
 *  判断
 *    {% if 条件 %}   {% endif %}
 *    {% if 条件 %}   {% elseif 条件 %}  {% endif %}
 *    {% if 条件 %}   {% else %}   {% endif %}
 *  循环
 *    {% for x in y %} {% endfor %}
 *    {% for key,val in data %}
 *    内置变量
 *      loop.index : 从1计算
 *      loop.index0: 从0计算
 *      loop.length: 长度
 *  定义变量:通过set方式 定义一个name变量
 *    {% set name = [0,0,4,12,3,13,5] %}
 * 
 *  get和post：
 *     get的问题：
 *        1.url的长度是有限制的，同理querystring的长度也是有长度限制的，数据量大的内容是不推荐get的方式进行传输
 *        2.get请求会缓存url，所以get请求的时候，url上的内容也会被缓存（即：get请求 浏览器会保存记录在历史记录中）
 *    querystring与get请求方式没有任何联系，无论是get还是post请求，querystring都可以传递数据
 */
